﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;

namespace VirtualVisionSpace
{
    public abstract class EnvironmentBase : IEnvironment
    {
        protected readonly Rectangle bounds;
        protected static Random random = new Random();
        Bitmap environment;
        protected Size size;
        public EnvironmentBase(Size size)
        {
            this.size = size;
            environment = new Bitmap(size.Width, size.Height);
            bounds = new Rectangle(new Point(), size);
        }

        protected abstract void OnEnvironmentChanged(Bitmap environment);

        #region IEnvironment 成员
        public System.Drawing.Size Size
        {
            get { return size; }
        }

        public Bitmap GetEnvironment(Rectangle rectVision)
        {
            lock (this.environment)
            {
                OnEnvironmentChanged(this.environment);
            }

            //环境区域
            Rectangle rectEnvironment = this.bounds;
            //环境与视觉相交
            rectEnvironment.Intersect(rectVision);
            //视觉图像
            Bitmap imageVision = new Bitmap(rectVision.Width, rectVision.Height);
            Rectangle rectImage = rectEnvironment;
            rectImage.Offset(-rectVision.Left, -rectVision.Top);
            lock (this.environment)
            {
                CopyBitmap(this.environment, rectEnvironment, imageVision, rectImage);
            }
            return imageVision;
        }

        #endregion
        /// <summary>
        /// 将源图像中的指定区域复制到目标图像指定区域
        /// </summary>
        /// <param name="bmpSource"></param>
        /// <param name="rectSource"></param>
        /// <param name="bmpDestination"></param>
        /// <param name="rectDestination"></param>
        public static void CopyBitmap(Bitmap bmpSource, Rectangle rectSource, Bitmap bmpDestination, Rectangle rectDestination)
        {
            if (rectSource.Size != rectDestination.Size) 
                throw new ApplicationException("Two size must be equal!|CopyBitmap");

            if (!(new Rectangle(new Point(), bmpSource.Size)).Contains(rectSource))
                throw new ApplicationException("Source bitmap rectangle must contain source rectangle!|CopyBitmap");

            if (!(new Rectangle(new Point(), bmpDestination.Size)).Contains(rectDestination))
                throw new ApplicationException("Destination bitmap rectangle must contain destination rectangle!|CopyBitmap");


            BitmapData dataSource = bmpSource.LockBits(rectSource, ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
            BitmapData dataDestination = bmpDestination.LockBits(rectDestination, ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb);

            IntPtr pSource = dataSource.Scan0;
            byte[] byteSource = new byte[rectSource.Width * rectSource.Height * 3];
            Marshal.Copy(pSource, byteSource, 0, byteSource.Length);

            IntPtr pDestination = dataDestination.Scan0;
            byte[] byteDestination = new byte[rectDestination.Width * rectDestination.Height * 3];
            Marshal.Copy(pDestination, byteDestination, 0, byteDestination.Length);

            for (int index = 0; index < byteDestination.Length; index++)
            {
                byteDestination[index] = byteSource[index];// = (byte)random.Next(byte.MaxValue);
            }

            Marshal.Copy(byteSource, 0, pSource, byteSource.Length);
            Marshal.Copy(byteDestination, 0, pDestination, byteDestination.Length);

            bmpSource.UnlockBits(dataSource);
            bmpDestination.UnlockBits(dataDestination);
        }
    }
}
